<?php
/**
 * Spectus Object Relation Mapper
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 *
 * @category	Spectus
 * @package		Spectus_Default
 * @copyright	Copyright (c) 2008-2009
 * @author		Mient-jan Stelling
 * @license		MIT License  http://en.wikipedia.org/wiki/MIT_License 
 */

/**
 * Spectus_Default_Table_Abstract
 *
 * @todo major recode of class 
 * @author Mient-jan Stelling
 **/
abstract class Spectus_Default_Table_Abstract extends Zend_Db_Table_Abstract
{

	// Custom row class protected $_rowclass = 'Dao_Row';		
	protected $_rowClass = 'Spectus_Default_Table_Row';
	protected $_rowsetClass = 'Spectus_Default_Table_Rowset';
	
	// Has one
	protected $_hasOne = array();

	// Has many
	protected $_hasMany = array();

	// Has belongs to
	protected $_belongsTo = array();

	// collection of ManyToMany
	private $_manyToMany = array();

	// is set true when in a query SQL_CALC_FOUND_ROWS is used
	private $SQL_CALC_FOUND_ROWS = FALSE;
	
	public function __construct()
	{
			// check _belongsTo
		foreach( $this->_belongsTo as $strClassName => $arrClassVars )
		{
			// var_dump($strClassName);
			if( in_array( $strClassName, $this->_hasMany ) )
			{
				$arrTableNames[] = get_class( $this );
				$arrTableNames[] = $arrClassVars['refTableClass'];
				asort($arrTableNames);
				
				$strNewTableClassName = implode('',$arrTableNames);
				$this->_manyToMany[ $strClassName ] = $arrClassVars;
				$this->_manyToMany[ $strClassName ]['refTableClass'] = $strNewTableClassName;
				
				$this->_dependentTables[] = $strNewTableClassName;
			}
			else
			{
				$this->_referenceMap[ $strClassName ] = $arrClassVars;
			}
		}
		
		// check hasOne
		foreach( $this->_hasMany as $strClassName => $arrSettings )
		{
			$blnIsset = FALSE;
			foreach ( $this->_belongsTo as $arrSubSettings )
			{
				if( $arrSubSettings['refTableClass'] == $arrSettings['refTableClass'] )
				{
					$blnIsset = TRUE;
				}
			}
			
			if( !$blnIsset)
			{
				$this->_dependentTables[] = $arrSettings['refTableClass'];
			}
		}
		
		//var_dump( __CLASS__, $this->_dependentTables );
		// exit();
		parent::__construct();
	}
	
	public function findAndReplace( $argStrColumnName, $argStrFind, $argStrReplace )
	{
		$this->_db->query('
			UPDATE `' . $this->_name . '`
			SET `' . $argStrColumnName . '` = REPLACE( `' . $argStrColumnName . '`, "' . $argStrFind . '", "' . $argStrReplace . '")
			WHERE `' . $argStrColumnName . '` LIKE ("%' . $argStrFind . '%")
		');
	}

	public function fetchAllFilterByColumn( array $arrColumns )
	{
		$objSelect = $this->select();
		
		foreach( $arrColumns as $strColumnName => $strValue )
		{
			if( in_array($strColumnName, $this->_cols ))
			{
				$objSelect->where('`' . $strColumnName . '` = ?', $strValue );
			}
		}
		
		return $this->fetchAll( $objSelect );
	}


	public function info( $argStr = NULL )
	{
		switch( $argStr )
		{
			case 'manyToMany':
			{
				return $this->_manyToMany;
				break;
			}
			
			case 'hasOne':
			{
				return $this->_hasOne;
				break;
			}
			
			case 'hasMany':
			{
				return $this->_hasMany;
				break;
			}
			
			case 'belongsTo':
			{
				return $this->_belongsTo;
				break;
			}
			
			case 'specialCols':
			{
				return ( empty($this->_specialCols) ? NULL : $this->_specialCols );
				break;
			}
			
			case 'primary':
			{
				return $this->_primary;
				break;
			}
		}
		
		return parent::info( $argStr );
	}

	/**
	 * Enter description here...
	 *
	 * @param array $argArrIds
	 * @return Spectus_Default_Table_Rowset_Abstract
	 */
	public function findByIds( array $argArrIds = array() )
	{
		if( count( $argArrIds) > 0 )
		{
			$objSelect = $this->select()
				->where( current( (array) $this->_primary ) . ' IN (' . implode(',', $argArrIds ) . ')');
			
			return $this->fetchAll( $objSelect );
		}
		else 
		{
			return $this->createRowset();
		}
	}
	
	public function createRowset( array $argArrData = array() )
	{
		Zend_Loader::loadClass($this->_rowsetClass);
		return new $this->_rowsetClass(array(
            'table'    => $this,
            'data'     => $argArrData,
            'readOnly' => TRUE,
            'rowClass' => $this->_rowClass,
            'stored'   => true
        ));
		
	}

	/**
	 * Enter description here...
	 *
	 * @param array $argArrIds
	 * @return Spectus_Default_Table_Row_Abstract
	 */
	public function findById( $argIntId )
	{
		$objSelect = $this->select()
			->where( current( (array) $this->_primary ) . ' = ?', $argIntId );
		
		return $this->fetchRow( $objSelect );
	}
	
	/**
	 * return total rows
	 *
	 * @return double
	 */
	public function count()
	{
		if( $this->SQL_CALC_FOUND_ROWS == FALSE )
		{
			$objSelect = $this->select()
				->from($this->_name,array('total_count' => 'COUNT(*)'))
				->limit(1);
			
			return (double) $this->fetchRow( $objSelect )->total_count;
		}
		else
		{
			$this->SQL_CALC_FOUND_ROWS = FALSE;
			return $this->foundRows();
		}
	}
	
	/**
	 * return total rows
	 *
	 * @return double
	 */
	public function foundRows()
	{
        $sql = "SELECT FOUND_ROWS() AS theCount";
        $stmt = $this->_db->query($sql);
        $row = $stmt->fetch();
        
       return (double) $row['theCount'];
	}

	public function emptyTable()
	{
		// $objDb = $this->getAdapter();
		$this->_db->query('TRUNCATE TABLE `' . $this->_name . '`');
	}
}